package com.jsu.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hankcs.hanlp.collection.sequence.SString;
import com.jsu.user.mapper.IntegralRuleMapper;
import com.jsu.user.mapper.PrizeMapper;
import com.jsu.user.mapper.WebUserMapper;
import com.jsu.user.service.WebPrizeService;
import com.jsu.user.service.WebRuleService;
import lombok.extern.slf4j.Slf4j;
import org.example.model.common.dtos.ResponseResult;
import org.example.model.common.enums.RedisCodeEnum;
import org.example.model.common.enums.WebHttpCodeEnum;
import org.example.model.user.pojo.PointDetail;
import org.example.model.user.pojo.Prize;
import org.example.model.user.pojo.Rule;
import org.example.model.user.pojo.User;
import org.example.utils.common.IdsUtils;
import org.example.utils.common.RedisCache;
import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Date;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
@Transactional
public class WebPrizeServiceImpl extends ServiceImpl<PrizeMapper, Prize> implements WebPrizeService {
    @Autowired
    private PrizeMapper prizeMapper;
    @Autowired
    private WebUserMapper userMapper;
    @Autowired(required = false)
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private WebUserServiceImpl userService;
    @Autowired
    private PointDetailServiceImpl pointDetailService;
    private static final ObjectMapper mapper = new ObjectMapper();


    /**
     * 活动奖品列表
     * @return prize集合
     */
    @Override
    public ResponseResult getPrize() {
        List<Prize> prizes = prizeMapper.selectList(null);
        if(prizes.size()==0||prizes.isEmpty())
            return ResponseResult.errorResult(WebHttpCodeEnum.DATA_NOT_EXIST,"还没有奖品");
        return ResponseResult.okResult(prizes);
    }

    /**
     * 管理端修改奖品信息
     * @param prize
     * @return
     */
    @Override
    public ResponseResult updatePrize(Prize prize) {
        String prizeStockKey = RedisCodeEnum.PRIZE.getMsg()+prize.getPkId();
        stringRedisTemplate.opsForValue().getOperations().delete(prizeStockKey);
        try {
            stringRedisTemplate.opsForValue().set(prizeStockKey,mapper.writeValueAsString(prize));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        int count = prizeMapper.updateById(prize);
        if(count<=0)
            return ResponseResult.errorResult(WebHttpCodeEnum.FAIL,"失败");
        return ResponseResult.okResult(200,"成功");
    }

    /**
     * 删除奖品信息
     * @param id
     * @return
     */
    @Override
    public ResponseResult deletePrize(int id) {
        String prizeStockKey = RedisCodeEnum.PRIZE.getMsg()+id;
        stringRedisTemplate.opsForValue().getOperations().delete(prizeStockKey);
        int count = prizeMapper.deleteById(id);
        if(count<=0)
            return ResponseResult.errorResult(WebHttpCodeEnum.FAIL,"删除失败");
        return ResponseResult.okResult(200,"删除成功");
    }

    /**
     * 兑换奖品
     * @param id
     * @return
     */
    @Override
    public ResponseResult exchangePrize(int id) {
        //1.查询用户当前积分是否足够
//        User user = userService.getUser();
        String phone = "19574422385";
        log.info("当前用户的手机号码为:"+phone);
        User user = userMapper.selectByPhone(phone);
//        log.info("当前用户的id为:{}",user.toString());
        if(user==null)
            return ResponseResult.errorResult(WebHttpCodeEnum.DATA_NOT_EXIST,"用户信息不存在");
        //2.判断用户积分和库存是否足够
        //2.1获取奖品信息
        Prize prize = prizeMapper.selectById(id);
        log.info("当前奖品积分为:{}",prize.getIntegral());
        log.info("当前用户积分为:{}",user.getIntegral());
        //2.2判断积分
        if (prize.getIntegral()>user.getIntegral()) {
            return ResponseResult.errorResult(WebHttpCodeEnum.FAIL,"积分不足");
        }
        //2.3判断库存

        String prizeStockKey = RedisCodeEnum.PRIZE.getMsg()+id;
        String stockValue = stringRedisTemplate.opsForValue().get(prizeStockKey);
        if(stockValue==null) {
            prize = getBaseMapper().selectById(id);
        }
        else {
            try {
                prize = mapper.readValue(stockValue,Prize.class);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
        int stock = prize.getNum();

        // 判断库存是否足够
        if (stock <= 0) {
            return ResponseResult.errorResult(WebHttpCodeEnum.FAIL, "奖品库存不足");
        }

        // 加锁
        String lockKey = RedisCodeEnum.PRIZE_EXCHANCE.getMsg() + id;
        Boolean locked = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "locked", 5, TimeUnit.SECONDS);

        try {
            if (locked != null && locked) {
                // 再次判断库存，防止在加锁期间发生变化
                stockValue = stringRedisTemplate.opsForValue().get(prizeStockKey);
                try {
                    prize = mapper.readValue(stockValue,Prize.class);
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
                stock = prize.getNum();

                if (stock <= 0) {
                    return ResponseResult.errorResult(WebHttpCodeEnum.FAIL, "奖品库存不足");
                }
                //更新用户积分
                user.setIntegral(user.getIntegral()-prize.getIntegral());
                prize.setNum(prize.getNum()-1);
                boolean a  = userService.updateById(user);
               log.info("更新用户积分："+a);
               if(!a)
                   return ResponseResult.errorResult(WebHttpCodeEnum.FAIL,"兑换失败");
               //更新数据库和redis中的库存
                stringRedisTemplate.opsForValue().getOperations().delete(prizeStockKey);
                String json = mapper.writeValueAsString(prize);
                stringRedisTemplate.opsForValue().set(prizeStockKey,json);
                log.info("redis中已经更新，修改数据库中的库存信息");
                //存储积分明细
                LocalDate now = LocalDate.now();
                PointDetail pointDetail = new PointDetail(user.getPkId(),prize.getPkId(),-prize.getIntegral(), Date.valueOf(now));
                log.info("存储积分明细："+pointDetail.toString());
                ResponseResult result = pointDetailService.addPointDetail(pointDetail);
                if(result.getCode()!=200){
                    return ResponseResult.errorResult(WebHttpCodeEnum.FAIL,"存储兑换记录失败");
                }
                return updatePrize(prize);

            } else {
                return ResponseResult.errorResult(WebHttpCodeEnum.FAIL, "兑换失败，请稍后重试");
            }
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        } finally {
            // 释放锁
            stringRedisTemplate.delete(lockKey);
        }
    }

    /**
     * 创建奖品
     * @param prize
     * @return
     */
    @Override
    public ResponseResult createPrize(Prize prize) {
        prize.setPkId(UUID.randomUUID().version());
        //存在数据库中
        int count = getBaseMapper().insert(prize);
        //存在redis中
        try {
            stringRedisTemplate.opsForValue().set(RedisCodeEnum.PRIZE.getMsg()+prize.getPkId(),mapper.writeValueAsString(prize));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        if(count<=0)
            return ResponseResult.errorResult(WebHttpCodeEnum.FAIL,"创建失败");
        return ResponseResult.okResult(200,"创建成功");
    }

//    /**
//     * 上传奖品图片
//     * @param file
//     * @return
//     */
//    @Override
//    public ResponseResult uploadPrizeImage(String file) {
//        //TODO 上传图片
//        return ResponseResult.okResult(200,"上传成功");
//    }

    /**
     * 搜索奖品
     *
     * @param keyword
     * @return
     */
    @Override
    public ResponseResult searchPrize(String keyword) {
        log.info("搜索关键字为："+keyword);
        List<Prize> prizes = getBaseMapper().searchPrizesByKeyword(keyword);
        if (prizes.size() == 0)
            return ResponseResult.errorResult(WebHttpCodeEnum.DATA_NOT_EXIST,"没有找到相关奖品");
        return ResponseResult.okResult(prizes);
    }

    /**
     * 批量删除奖品信息
     * @param ids
     * @return
     */
    @Override
    public ResponseResult batchDeletePrize(Integer[] ids) {
        for (int i = 0; i < ids.length; i++){
            String prizeStockKey = RedisCodeEnum.PRIZE.getMsg()+ids[i];
            stringRedisTemplate.opsForValue().getOperations().delete(prizeStockKey);
        }
        List<Integer> idList = ids.length>0? Arrays.asList(ids):new ArrayList<>();
        int count = getBaseMapper().deleteBatchIds(idList);
        if(count<=0)
            return ResponseResult.errorResult(WebHttpCodeEnum.FAIL,"删除失败");
        return ResponseResult.okResult(200,"删除成功");
    }


}
